package com.pj.lib.auraServer.components.lbs;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Map;

import com.pj.lib.auraServer.app.Server;
import com.pj.lib.auraServer.app.ServerComponent;
import com.pj.lib.auraServer.app.listeners.OnLocationUpdate;
import com.pj.lib.auraServer.app.properties.AuraProperties;
import com.pj.lib.auraServer.app.properties.Properties;
import com.pj.lib.auraServer.components.DB.DB;
import com.pj.lib.auraServer.components.DB.tables.UserLocation;
import com.pj.lib.auraServer.components.connection.ClientThread;
import com.pj.lib.auraServer.components.connection.NetworkManager;
import com.pj.lib.auraServer.exceptions.AuraServerException;
import com.pj.lib.aura.connection.LocationModel;
import com.pj.lib.auraServer.utils.Log;

public class LocationsPropagationComponent extends ServerComponent implements Runnable{

	private ArrayList<Map<String, Object>> mLocations;
	private ArrayList<LocationModel> tempLocations;
	private Boolean mLocationChanged = false;
	
	Thread thread;
	
	private long mRefreshTime;
	
	public LocationsPropagationComponent(Server server) {
		super(server);
		
		addOnUpdateLocation(new OnLocationUpdate() {
			
			@Override
			public void locationReceived(int userId, double[] loc, float precision) {
				setLocationChanged(true);
			}
		});
		
		mRefreshTime = ((AuraProperties)getServer().getProperties(Properties.PROP_AURA)).SERVER_LOCATION_REFRESH_TIME
		*1000;
		
		thread =  new Thread(this);
		thread.start();
		
		
		
	}

	private synchronized void setLocationChanged(Boolean chng) {
		this.mLocationChanged = chng;
	}
	private synchronized Boolean getLocationChanged() {
		return this.mLocationChanged;
	}
	
	ArrayList<ClientThread> clients;
	@Override
	public void run() {
		while(true) {
			try {
				clients = ((NetworkManager)getServer().getComponent(COMPONENT_NETWORK_MANAGER)).getClients();
				
				if(getLocationChanged()) {
					//TODO check this out
					mLocations = ((UserLocation)getDB().getInstance(DB.INSTANCE_USER_LOCATION))
										.get(null, null, null, 
												" ORDER BY " + UserLocation.COLUMN_TIME + 
												" LIMIT 1;");
					tempLocations = new ArrayList<LocationModel>();
					for(Map<String, Object> loc : mLocations) {
						tempLocations.add(new LocationModel((Integer)loc.get(UserLocation.COLUMN_USER_ID), 
								(Double)loc.get(UserLocation.COLUMN_LATITUDE), 
								(Double)loc.get(UserLocation.COLUMN_LONGITUDE), 
								(Date)loc.get(UserLocation.COLUMN_TIME), 
								(Float)loc.get(UserLocation.COLUMN_PRECISION)));
					}
					for(ClientThread ct : 
						clients) {
	
							ct.handleSendUserLocalizations(tempLocations);

					}
					
				}
				
				
				Thread.sleep(mRefreshTime);

				
			} catch (AuraServerException e) {
				Log.s(this, Log.getStackTrace(e));
			} catch (SQLException e) {
				Log.s(this, Log.getStackTrace(e));
			} catch (InterruptedException e) {
				Log.s(this, Log.getStackTrace(e));
			}
		}
	}

}
